package ext.tianma.bom.workflow;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;

import wt.doc.WTDocument;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.WTObject;
import wt.fc.collections.WTArrayList;
import wt.lifecycle.LifeCycleHelper;
import wt.lifecycle.LifeCycleManaged;
import wt.lifecycle.State;
import wt.part.WTPart;
import wt.part.WTPartHelper;
import wt.part.WTPartMaster;
import wt.part.WTPartUsageLink;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.type.ClientTypedUtility;
import wt.util.WTException;
import wt.vc.wip.WorkInProgressHelper;
import wt.workflow.engine.WfProcess;

import com.ptc.core.meta.common.TypeIdentifier;

import ext.com.core.CoreUtil;
import ext.tianma.project.relatedproduct.CreateProjectBusiness;
import ext.tianma.version.ComToolUtil;

/**Description: 【BOM流程】里会用到的工具方法
 * @author    :  YangWen
 * @create at :  2013-9-22   上午10:25:25
 */
public class BOMBusinessUtil {
	

	/**
	 * 展示是否输出log信息
	 */
	private static boolean isShow = true;
	
	/**
	 * 私有构造函数，防止实例化
	 */
	private BOMBusinessUtil(){
		
	}
	
	/**输出log信息
	 * @param info
	 */
	private static void out(String info){
		if(isShow)
			System.out.println("【BOM流程】里会用到的工具方法:"+BOMBusinessUtil.class.getName()+":"+info);
	}
	
	
	
	
    /**YW
     * 递归获取指定部件下的所有部件
     * @param part WTPart对象
     * @return ArrayList<WTPart>对象
     */
    public static ArrayList<WTPart> getAllSubPart(WTPart part) {
		ArrayList<WTPart> result = new ArrayList<WTPart>();
		if (part != null) {
		    try {
		    	//获得部件所关联的所有部件
				QueryResult allLink = WTPartHelper.service.getUsesWTPartMasters(part);
								
				while (allLink.hasMoreElements()) {
				    WTPartUsageLink link = (WTPartUsageLink) allLink.nextElement();
				    WTPart subPart = (WTPart) CreateProjectBusiness.getLatestWTPartByMaster((WTPartMaster) link.getUses());
				    result.add(subPart);
				    result.addAll(getAllSubPart(subPart));
				}
		    } catch (Exception e) {
		    	e.printStackTrace();
		    }
		}
		return result;
    }
    
    
    /**YW
     * 判断指定对象是否属于fullType对象或者其子对象
     * @param obj WTObject对象
     * @param fullType 内部全程，如wt.doc.WTDocument|com.tianma.pdmtest.DrawingDoc
     * @return 如果是，则返回true
     * @throws WTException 
     */
    public static boolean isSubObject(WTObject obj , String fullType) throws WTException{
    	
    	if(ComToolUtil.isEmpty(obj)||ComToolUtil.isEmpty(fullType))
    		return false;
    		    	
    	String innerName = getInnerFullName(obj);
    	if(ComToolUtil.isEmpty(innerName))
    		return false;
    	
    	Hashtable<String , String> subTypeName = getAllSubTypeInnerFullName(fullType);	
    	if(subTypeName == null || subTypeName.size() == 0)
    		return false;	    	
    	
      	Iterator<String> iterator = subTypeName.keySet().iterator();					
    	while(iterator.hasNext()){
    		String key = (String) iterator.next();
    		String value = (String) subTypeName.get(key);
    		if (value.trim().equals(innerName.trim())) 
    		    return true;    		
    	}
    	
    	return false;
    }
	

    
    /**YW
     * 获得指定对象的内部全名
     * @param obj 指定的WTObject
     * @return String 如wt.doc.WTDocument|com.tianma.pdmtest.DrawingDoc|com.tianma.pdmtest.DesignDoc
     * @throws WTException
     */
    public static String getInnerFullName(WTObject obj) throws WTException {
  		if (ComToolUtil.isEmpty(obj))
  		    return null;
  		
  		TypeIdentifier typeIdentifier = ClientTypedUtility.getTypeIdentifier(obj);  		
  		return typeIdentifier.getTypename();
    }
  
    
    
    
    /**YW
	 * 获得指定内部全称下的所有子类型(包括当前对象本身)，如果当前类型下包含子类，则只返回当前一个对象类型
	 * @param parentInnerFullName String，指定的一个拥有子类型的全称
	 * 如wt.doc.WTDocument|com.tianma.pdmtest.DrawingDoc
	 * @return Hashtable<String , String>对象，【子类型的中文名称，子类型的全部英文字段】
	 * @throws WTException 
	 */
	public static Hashtable<String , String> getAllSubTypeInnerFullName(String parentInnerFullName) throws WTException {
		
		if(ComToolUtil.isEmpty(parentInnerFullName))
			return null;
		
		Hashtable<String , String> result = new Hashtable<String, String>();
		
		Locale locale = Locale.CHINA;
		
		
		out("getAllSubTypeInnerFullName   parentInnerFullName="+parentInnerFullName);
		
		//通过英文字段全称获取相应的类型标识对象
		TypeIdentifier parentTypeId = com.ptc.core.foundation.type.server.impl.TypeHelper.getTypeIdentifier(parentInnerFullName);		
		if(parentTypeId == null){
			out("通过【"+parentInnerFullName+"】此值，无法找到相应的类型标识对象，可能此值不是全称内部名称，直接返回空!");
			return null;
		}
			
		out("getAllSubTypeInnerFullName   parentTypeId="+parentTypeId);
		
		Set<TypeIdentifier> set=com.ptc.core.htmlcomp.util.TypeHelper.getSubTypesForType(parentTypeId,locale);
		//一般情况下，此情况是不会出现的，如非是系统的bug，因为系统返回的值里面已经包含了父类型值
        if(set == null || set.size() == 0){
        	out("通过【"+parentInnerFullName+"】此值，可以找到相应的类型标识对象，但是它下面不含任何子类型!");        	
        	String parentTypeShowName=com.ptc.core.foundation.type.server.impl.TypeHelper.getLocalizedTypeString(parentTypeId, locale);
			String parentTypeInnerName=parentTypeId.getTypename();
			result.put(parentTypeShowName, parentTypeInnerName);
        	return result;
        }
        		
		Iterator<TypeIdentifier> iterator = set.iterator();
        
        //子类型的中文名称
        String subTypeShowName=null;
        //子类型的所对应的英文全称
        String subTypeInnerName=null;
                
        while(iterator.hasNext()) {
        	TypeIdentifier subTypeId = (TypeIdentifier)iterator.next();
        	subTypeShowName=com.ptc.core.foundation.type.server.impl.TypeHelper.getLocalizedTypeString(subTypeId, locale);
			subTypeInnerName=subTypeId.getTypename();
			
			out("子类型的名称："+subTypeShowName +",所对应于的英文名称为："+subTypeInnerName);
			
			//添加【子类型的中文名称，子类型的全部英文字段】
			//【设计图纸, wt.doc.WTDocument|com.tianma.pdmtest.DrawingDoc|com.tianma.pdmtest.DesignDoc】				
			result.put(subTypeShowName, subTypeInnerName);							
		}		
		
		return result;
	}
	
	
	/**获取指定对象相关的所有进程
     * @param obj WTObject对象
     * @return ArrayList<WfProcess>对象
     * @throws WTException
     */
    public static ArrayList<WfProcess> getRreferenceProcess(WTObject obj) throws WTException {
		ArrayList<WfProcess> result = new ArrayList<WfProcess>();
		QueryResult processQR = queryRreferenceProcess(obj);
		while (processQR.hasMoreElements()) {
		    Object process = processQR.nextElement();
		    result.add((WfProcess) process);
		}
		return result;
    }
    
    
    /**获取指定对象相关的所有进程
     * @param obj WTObject对象
     * @return QueryResult对象，即进程的集合
     * @throws WTException
     */
    @SuppressWarnings("deprecation")
	private static QueryResult queryRreferenceProcess(WTObject obj) throws WTException {
    	if(obj == null)
    		return null;
		ReferenceFactory factory = new ReferenceFactory();
		String ref = factory.getReferenceString(obj);
		QuerySpec processQS = new QuerySpec(WfProcess.class);
		SearchCondition sc = new SearchCondition(WfProcess.class, "businessObjReference", "=", ref);
		processQS.appendSearchCondition(sc);	
		return PersistenceHelper.manager.find(processQS);
    }
    
    
    
    /**YW
     * 设置所有随签对象的生命周期状态为目标状态
     * @param reviewObjs WTArrayList，即随签对象集合
     * @param targetState String ，即目标生命周期状态 ，
		UNDERREVIEW.value=正在审阅
		REWORK.value=重新工作
		NewProduct.value=新品
     * @throws WTException 
     */
    @SuppressWarnings("deprecation")
	public static void setLifeCycleState(WTArrayList reviewObjs, String targetState) throws WTException {
    	
		if(ComToolUtil.isEmpty(targetState))
			return ;
		
		if(reviewObjs == null)
			out("随签对象里所含对象为空");
		else
			out("随签对象里所含对象个数是："+reviewObjs.size());
		
		//reviewObjs = getLatestWTPartByView(reviewObjs);
		
		out("目标生命周期状态的英文名是："+targetState);
					
		if(reviewObjs!=null && reviewObjs.size() > 0){
			for(int i=0;i<reviewObjs.size();++i){
				Persistable obj = null;
				try {
					obj = reviewObjs.getPersistable(i);
				} catch (WTException e) {
					e.printStackTrace();
					throw new WTException("从随签对象里获取第"+(i+1)+"个值时出错，程序终止！");						
				}
				if (obj instanceof LifeCycleManaged) {
				    LifeCycleManaged lcm = (LifeCycleManaged) obj;
				    String currentlcmState = lcm.getLifeCycleState().toString();
				    out("欲处理的对象【"+lcm.getIdentity()+"】的当前生命周期状态是："+currentlcmState);
				    if (!currentlcmState.equalsIgnoreCase(targetState)) {
				    	out("正在处理对象【"+lcm.getIdentity()+"】的生命周期状态...");
				    	try {
							LifeCycleHelper.service.setLifeCycleState(lcm, State.toState(targetState));
							lcm = (LifeCycleManaged) PersistenceHelper.manager.refresh(lcm);
						}  catch (WTException e) {
								e.printStackTrace();
								throw new WTException("给当前的pbo对象设置生命周期状态时报错:\n" +
										"可能是当前对象【"+lcm.getIdentity()+"】没有【"+State.toState(targetState).getLocalizedMessage(Locale.CHINA)+"】这个状态，程序终止！");							
						}				    	
				    }
				    out("处理完后，对象【"+lcm.getIdentity()+"】的生命周期状态是："+lcm.getLifeCycleState().toString());
				}
		    }
		}		
	    		
    }
    
    
    
    /**输出
     * @param reviewObjs
     * @throws WTException
     */
    @SuppressWarnings("deprecation")
	public static void out(WTArrayList reviewObjs) throws WTException{
		
		if(reviewObjs!=null && reviewObjs.size() > 0){
			for(int i=0;i<reviewObjs.size();++i){
				Persistable obj = null;
				try {
					obj = reviewObjs.getPersistable(i);
				} catch (WTException e) {
					e.printStackTrace();
					throw new WTException("从随签对象里获取第"+(i+1)+"个值时出错，程序终止！");						
				}
				out(i+":"+obj.getIdentity());
		    }
		}
    }
    
    /**YW
     * 把指定集合里的每一个对象更新至最新版本
     * @param table ArrayList<WTPart>
     * @throws WTException
     */
    public static void getLatestWTPart(ArrayList<WTPart> table) throws WTException{
		
    	ArrayList<WTPart> temp = new ArrayList<WTPart>();
    	
		if(table!=null && table.size() > 0){
			for(int i=0;i<table.size();++i){
				WTPart part = table.get(i);		
				
				if(part == null){
					continue;
				}
				
				temp.add(WTPartToolUtil.getLatestWTPartByNumber(part.getNumber()));				
		    }
		}
		
		table.clear();
		table.addAll(temp);		
    }
    
    /**YW
     * 把指定集合里的每一个对象更新至最新版本
     * @param reviewObjs WTArrayList对象，只争对WTPart对象
     * @throws WTException
     */
    public static void getLatestWTPart(WTArrayList reviewObjs) throws WTException{
		
    	WTArrayList temp = new WTArrayList();
    	
		if(reviewObjs!=null && reviewObjs.size() > 0){
			for(int i=0;i<reviewObjs.size();++i){
				Persistable obj = null;
				try {
					obj = reviewObjs.getPersistable(i);
				} catch (WTException e) {
					e.printStackTrace();
					throw new WTException("从随签对象里获取第"+(i+1)+"个值时出错，程序终止！");						
				}
				
				if(obj == null || !(obj instanceof WTPart)){
					temp.add(obj);
					continue;
				}
				
				WTPart part = (WTPart)obj;
				
				temp.add(WTPartToolUtil.getLatestWTPartByNumber(part.getNumber()));		
				
				
				
		    }
		}
		
		reviewObjs.clear();
		reviewObjs.addAll(temp);
		
    }
    
    /**
     * 获取当前零部件的最新版本（与之之前视图相同）
     * 
     * add kwang 2013-12-18
     * @param reviewObjs
     * @throws WTException
     */
    public static WTArrayList getLatestWTPartByView(WTArrayList reviewObjs) throws WTException{
		
    	WTArrayList temp = new WTArrayList();
    	
		if( reviewObjs != null ){
			int size = reviewObjs.size() ;
			
			for(int i=0 ; i< size ;++i ){
				Persistable persistable = null;
				try {
					persistable = reviewObjs.getPersistable(i);
					
					if( persistable != null && persistable instanceof WTPart ){
						WTPart aPart = ( WTPart ) persistable ;
						
						aPart = CoreUtil.getWTPartByMasterAndView( (WTPartMaster) aPart.getMaster() , aPart.getViewName() ) ;
						
						if( aPart != null ){
							temp.add(aPart) ;
						}						
					}
				} catch (WTException e) {
					e.printStackTrace();
					throw new WTException("从随签对象里获取第"+(i+1)+"个值时出错，程序终止！");						
				}
		    }
		}
		
		return temp ;
    }

	/**YW
     * 检查指定对象里的每一个对象(WTPart)，是否被检出，
     * 如果有被检出的，则抛出异常
     * @param reviewObjs WTArrayList对象，只争对WTPart或者WTDocument对象
     * @throws WTException
     */
    public static void isCheckedOutToWTPart(WTArrayList reviewObjs) throws WTException{
    	
    	//保存被检出部件的编号
		ArrayList<String> checkoutPartNumberList = new ArrayList<String>();
		if(reviewObjs!=null && reviewObjs.size() > 0){
			for(int i=0;i<reviewObjs.size();++i){
				Persistable obj = null;
				try {
					obj = reviewObjs.getPersistable(i);
				} catch (WTException e) {
					e.printStackTrace();
					throw new WTException("从随签对象里获取第"+(i+1)+"个值时出错，程序终止！");						
				}
		    	if(obj == null)
		    		continue;
		    		    	
		    	if(obj instanceof WTPart){
			    	if(WorkInProgressHelper.isCheckedOut((WTPart)obj)){
					    checkoutPartNumberList.add(((WTPart)obj).getNumber());
					}
		    	}else if(obj instanceof WTDocument){
			    	if(WorkInProgressHelper.isCheckedOut((WTDocument)obj)){
					    checkoutPartNumberList.add(((WTDocument)obj).getNumber());
					}
		    	}
		    	
			}
		}
	    
	    if (!checkoutPartNumberList.isEmpty()) {
	    	String checkoutPart = "";
	    	for(String number : checkoutPartNumberList)
	    		checkoutPart += "\n" + number;
	    	throw new WTException("以下对象编号被检出："+checkoutPart);
	    }	 
    	
    }


    
    /**从随签审对象reviewObjs里移除掉指定的对象pbo
     * @param reviewObjs
     * @throws WTException
     */
    @SuppressWarnings("deprecation")
	public static void remove(WTArrayList reviewObjs , Persistable pbo) throws WTException{
		
		if(reviewObjs!=null && reviewObjs.size() > 0){
			for(int i=0;i<reviewObjs.size();++i){
				Persistable obj = null;
				try {
					obj = reviewObjs.getPersistable(i);
				} catch (WTException e) {
					e.printStackTrace();
					throw new WTException("从随签对象里获取第"+(i+1)+"个值时出错，程序终止！");						
				}
				if(obj.getIdentity().trim().equals(pbo.getIdentity().trim())){
					reviewObjs.remove(i);
					i--;
				}
		    }
		}
    }
    
    
}
